/**************************************************************
* @brief:       stream handle
* @date:         20200725
* @update:
* @auth:         Wite_Chen
* @copyright:
*
***************************************************************/
#pragma once
#include "Common.h"
#include "StreamHandle.h"




class RtspStreamHandle : public StreamHandle
{
private:
    static int read_interrupt_cb(void* pContext);
    static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts);
    int hw_decoder_init(AVCodecContext *ctx, const enum AVHWDeviceType type);

public:
    RtspStreamHandle();
    ~RtspStreamHandle();
    virtual bool StartDecode(const StreamInfo& infoStream);
    virtual void StopDecode();
    virtual void GetRtmpUrl(std::string& strRtmp);
    void GetVideoSize(int& width, int & height);
    void PushFrame(const cv::Mat& frame);
    bool PopFrame(cv::Mat& frame);

private:
    bool start_decode();
    // input
    bool open_input_stream();
    bool open_codec_context(int& nStreamIndex,
        AVCodecContext **dec_ctx,
        AVFormatContext *fmt_ctx,
        enum AVMediaType type);
    void close_input_stream();
    // output
    bool open_output_stream(AVFormatContext*& pFormatCtx, bool bRtmp = false);
    void close_output_stream();
    void do_decode();
    void push_packet(const AVPacket& packet);
    bool decode_video_packet(AVPacket* packet);
    bool decode_audio_packet(const AVPacket& packet);
    void save_stream(AVFormatContext* pFormatCtx, const AVPacket& packet);
    void release_output_format_context(AVFormatContext*& pFmtContext);
    std::string get_filename(int nType = kFileTypePicture);
    std::string get_error_msg(int nErrorCode);
    cv::Mat avframe_to_mat(const AVFrame * frame);

private:
    bool m_bExit;
    bool m_bFirstRun;
    std::string m_strToday;
    StreamInfo m_infoStream;
    AVFormatContext* m_pInputAVFormatCtx;
    AVCodecContext* m_pVideoDecoderCtx;
    AVCodecContext* m_pAudioDecoderCtx;
    AVFormatContext* m_pOutputFileAVFormatCtx;
    AVFormatContext* m_pOutputStreamAVFormatCtx;
    AVBufferRef *m_pHDCtx;
    SwsContext* m_pSwsCtx;
    bool m_bInputInited;
    bool m_bOutputInited;
    // decode
    std::thread m_thDecode;
    std::mutex m_mtPacket;
    std::condition_variable m_cvFrame;
    std::list<AVPacket> m_listPacket;

    // cache the frame
    int m_nFrame;
    std::mutex m_mtFrame;
    std::list<cv::Mat> m_listFrame;
    ThreadPool m_poolSavePic;

};
